# src/ui/button_delegate.py
import logging

from PySide6.QtCore import QEvent, QModelIndex, QRect, QSize, Qt, Signal
from PySide6.QtGui import QColor, QPalette
from PySide6.QtWidgets import (
    QApplication,
    QStyle,
    QStyledItemDelegate,
    QStyleOptionButton,
)

from src.utils.utils import (
    IN_PRINT_LIST_IDS,
)

logger = logging.getLogger(__name__)


class ButtonDelegate(QStyledItemDelegate):
    buttonClicked = Signal(QModelIndex, int)  # row, button_index

    def __init__(self, button_texts, parent=None):
        super().__init__(parent)
        self.button_texts = button_texts
        self._pressed = None  # (index, button_index)

    def paint(self, painter, option, index):
        try:
            data = index.model().data(index, Qt.ItemDataRole.UserRole)
            deactive = True
            if data and data.id in IN_PRINT_LIST_IDS:
                deactive = False
            btn_count = len(self.button_texts)
            btn_width = option.rect.width() // btn_count
            for i, text in enumerate(self.button_texts):
                btn_rect = QRect(
                    option.rect.left() + i * btn_width,
                    option.rect.top(),
                    btn_width,
                    option.rect.height(),
                )
                opt_btn = QStyleOptionButton()

                opt_btn.rect = btn_rect  # type: ignore
                opt_btn.text = text  # type: ignore
                opt_btn.state = (  # type: ignore
                    QStyle.StateFlag.State_Enabled | QStyle.StateFlag.State_Raised
                )
                if not deactive and i == 0:
                    opt_btn.palette.setColor(
                        QPalette.ColorRole.Button, QColor(10, 90, 230)
                    )
                    opt_btn.palette.setColor(
                        QPalette.ColorRole.ButtonText, QColor(255, 255, 255)
                    )
                if self._pressed == (index, i):
                    opt_btn.state |= QStyle.StateFlag.State_Sunken  # type: ignore
                QApplication.style().drawControl(
                    QStyle.ControlElement.CE_PushButton, opt_btn, painter
                )
        except Exception as e:
            logger.error(f"paint方法异常: {str(e)}")

    def editorEvent(self, event, model, option, index):
        try:
            if not index.isValid():
                return False
            btn_count = len(self.button_texts)
            btn_width = option.rect.width() // btn_count

            if event.type() == QEvent.Type.MouseButtonPress:
                if event.button() == Qt.MouseButton.LeftButton:
                    for i in range(btn_count):
                        btn_rect = QRect(
                            option.rect.left() + i * btn_width,
                            option.rect.top(),
                            btn_width,
                            option.rect.height(),
                        )
                        if btn_rect.contains(event.pos()):
                            self._pressed = (index, i)
                            return True
            elif event.type() == QEvent.Type.MouseButtonRelease:
                if event.button() == Qt.MouseButton.LeftButton and self._pressed:
                    pressed_index, pressed_btn = self._pressed
                    if pressed_index == index:
                        for i in range(btn_count):
                            btn_rect = QRect(
                                option.rect.left() + i * btn_width,
                                option.rect.top(),
                                btn_width,
                                option.rect.height(),
                            )
                            if btn_rect.contains(event.pos()) and i == pressed_btn:
                                self.buttonClicked.emit(index, i)
                                self._pressed = None
                                return True
                    self._pressed = None
            return super().editorEvent(event, model, option, index)
        except Exception as e:
            logger.error(f"editorEvent异常: {str(e)}")
            return False

    def sizeHint(self, option, index):
        style = QApplication.style()
        fm = option.fontMetrics  # 当前字体度量
        # 1. 找最宽文字
        max_text = max(self.button_texts, key=lambda t: fm.horizontalAdvance(t))
        # 2. 用真实按钮样式估算单按钮宽度
        opt = QStyleOptionButton()
        opt.text = max_text  # type: ignore
        # 3. 系统边距、框架、留白
        margin = style.pixelMetric(QStyle.PixelMetric.PM_ButtonMargin, opt)
        frame = style.pixelMetric(QStyle.PixelMetric.PM_DefaultFrameWidth, opt)
        content = fm.horizontalAdvance(max_text)
        single = (margin + frame) * 2 + content + 8  # 8 像素额外留白
        total = single * len(self.button_texts)
        button_base_height = fm.height()
        button_height = button_base_height + (margin + frame) * 2 + 8  # 添加额外空间
        # 4. 高度沿用默认行高
        return QSize(total, button_height)

    def createEditor(self, parent, option, index):
        return None
